#ifndef NETCLIENT_H
#define NETCLIENT_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QWebSocket>
#include <QProtobufSerializer>
#include <QNetworkReply>
#include "../model/data.h"
#include "gateway.qpb.h"
#include "user.qpb.h"
#include "friend.qpb.h"
#include"message_storage.qpb.h"
#include "message_transmit.qpb.h"
#include "notify.qpb.h"
#include "../toast.h"
#include "file.qpb.h"
#include "speech_recognition.qpb.h"



/**********************************************************************************************
 * 管理所有的和服务器通信的内容
 * NetClient  内部⼜分成  httpClient  和  websocketClient
 **********************************************************************************************/

namespace model
{
    class DataCenter;
} //end model

namespace network
{

    class NetClient : public QObject
    {
        Q_OBJECT
    public:
        explicit NetClient(model::DataCenter* dataCenter);
        void initWebSocket();   //准备好相关信号槽
        //发送身份认证请求
        void sendAuth();
        static QString makeRequestID();
        void pingHttp();    //测试Http1请求
    public:
        //发送请求
        QNetworkReply* sendHttpRequest(const QString& apiPath,const QByteArray& body);
        //处理服务器发送的请求
        void handleWsResponse(const my::NotifyMessage& notifyMessage);
        //处理服务器发的消息
        void handleWsMessage(const model::MessageInfo message);
        void handleWsRemoveFriend(const QString& userId);
        void handleWsApplyFriend(const model::UserInfo& userInfo);
        void handleWsApplyFriendProcess(const model::UserInfo userInfo,bool agree);
        void handleWsChatSessionCreate(const model::ChatSessionInfo& chatSessionInfo);

        //处理请求
        template <typename T>
        std::shared_ptr<T> handleHttpResponse(QNetworkReply* httpResp,bool& ok, QString& reason)
        {
            // a) 判定http请求是否出错
            if(httpResp->error() != QNetworkReply::NoError)
            {
                ok = false;
                reason = httpResp->errorString();
                httpResp->deleteLater();
                return std::shared_ptr<T>();
            }

            // b)拿到响应
            QByteArray respText = httpResp->readAll();

            // c)针对响应进行反序列化，解析成对象
            std::shared_ptr<T> pbResp = std::make_shared<T>();
            pbResp->deserialize(&this->serializer,respText);

            // d)判断业务上是否出错
            if(!pbResp->success())
            {
                ok = false;
                reason = pbResp->errmsg();
                httpResp->deleteLater();
                return std::shared_ptr<T>();
            }
            httpResp->deleteLater();
            return pbResp;
        }

        //获取个人信息
        void getMyself(const QString& loginSessionId);
        //获取好友列表
        void getFriendList(const QString& loginSessionId);
        //获取会话列表
        void getChatSessionList(const QString& loginSessionId);
        //获取好友申请列表
        void getApplyList(const QString& loginSessionId);
        //获取最近的消息列表
        void getRecentMessage(const QString& loginSessionId,const QString& chatSessionId,bool updateUi);
        //发送文本消息
        void sendMessage(const QString& loginSessionId,
                         const QString& chatSessionId,
                         const model::MessageType messageType,
                         const QByteArray& content,
                         const QString extraInfo);
        //接收消息
        void receiveMessage(const QString& chatSessionId);
        //修改昵称
        void changeNickName(const QString& loginSessionId,const QString& nickName);
        //修改个签
        void changeDesc(const QString& loginSessionId,const QString& desc);
        //获取验证阿门
        void getVerifyCode(const QString& phone);
        //修改手机号
        void changePhone(const QString& loginSessionId,const QString& phone,const QString& verifyCodeId,const QString& verifyCode);
        //修改头像
        void changeAvatar(const QString& loginSessionId,const QByteArray& avatar);
        //删除好友
        void deleteFriend(const QString& loginSessionId,const QString& userId);
        //添加好友
        void applyFriend(const QString& loginSessionId,const QString& userId);

        //同意好友申请
        void agreeFriendApply(const QString& loginSessionId,const QString& userId);
        //拒绝好友申请
        void rejectFriendApply(const QString& loginSessionId,const QString& userId);
        //创建群聊
        void createGroupChatSession(const QString& loginSessionId,const QList<QString>& userIdList);
        //获取成员列表
        void getMemberList(const QString& loginSessionId,const QString& currentSessionId);
        //搜索用户
        void searchUser(const QString& loginSessionId,const QString& searchKey);
        //搜索消息记录
        void getHistoryMessage(const QString& loginSessionId,const QString& currentChatSessionId,const QString& searchKey);
        void getHistoryMessageByTime(const QString& loginSessionId,const QString& currentChatSessionId,
                                     const QDateTime& beginTime,const QDateTime& endTime);
        //用户登录
        void userLogin(const QString& userName,const QString& password);
        //用户注册
        void userRegister(const QString& userName,const QString& password);
        //手机号登录
        void phoneLogin(const QString& phone,const QString& verifyCodeId,const QString& verifyCode);
        void phoneRegister(const QString& phone,const QString& verifyCodeId,const QString& verifyCode);

        //一个单独用来加载"文件的接口"
        void getSingleFile(const QString& loginSessionId,const QString& fileId);

        //语音转文字
        void speechConvertText(const QString& loginSessionId,const QString& fileId,const QByteArray& speechContent);
    private:
         //定义重要常量。ip都暂时使用本地的环回ip，端口号约定成 9000 和 9001
        const QString HTTP_URL = "http://101.42.171.159:9000";
        const QString WEBSOCKER_URL = "ws://101.42.171.159:9001/ws";


    private:

        //http客户端
        QNetworkAccessManager httpClient;
        //websocket客户端
        QWebSocket webSocketClient;

        //序列化器
        QProtobufSerializer serializer;

    private:
        model::DataCenter* dataCenter;
    signals:
    };
}

#endif // NETCLIENT_H
